#!/usr/bin/perl

######################################################################
package Swignition::GenericParser::eRDF;
######################################################################

use XML::LibXML qw(:all);

sub is_enabled
{
	my $this = shift;
	
	if ($this->{options}->{p_erdf})
	{
		return unless ($this->{Profiles}->{'http://purl.org/NET/erdf/profile'}
			|| !$this->{options}->{erdf_strict_profiles} );
		return 1;
	}
	
	return 0;
}

# Parse eRDF <URL:http://research.talis.com/2005/erdf/wiki/Main/RdfInHtml>.
sub consume
{
	my $this = shift;
	my $myurl = $this->uri('');

	foreach my $e ($this->{DOM}->getElementsByTagName('*'))
	{
		next unless ($e->getAttribute('class') || $e->getAttribute('rel') || $e->getAttribute('rev'));

		# Value
		my $content = Swignition::GenericParser::Utils::STRINGIFY($e);

		# Find eRDF-style parent node. i.e. nearest ancestor with @id set.
		my $parent = $e->getParentNode;
		my $subject = undef;
		my $about = $myurl;
		while (!defined $subject && $parent->nodeType==XML_ELEMENT_NODE)
		{
			if ($parent->getAttribute('id'))
				{ $subject = $parent; }
			else
				{ $parent = $parent->getParentNode(); }
		}
		if ($subject)
		{
			$about .= '#' . $subject->getAttribute('id');
			if (length $subject->getAttribute('href'))
			{
				$about = $this->uri($subject->getAttribute('href'));
			}
		}
		my $ParentSubject = $about;

		my ($MySubject, $addMySubject);
		if (length $e->getAttribute('id'))
		{
			$MySubject = $myurl.'#'.$e->getAttribute('id');
		}
		else
		{
			$MySubject = Swignition::GenericParser::Utils::BNodeURI($e, 'Node');
		}

		# Normalise @class, @rel, @rev and arrayise.
		my @things = ();
		my $class = $e->getAttribute('class');
		$class =~ s/(^\s+|\s+$)//g;
		$class =~ s/\s+/ /g;
		my @class = split / /, $class;
		foreach my $c (@class)
			{ push @things, [('class', $c)]; }
		if ($e->tagName =~ /^(a|area|link)$/i)
		{
			$class = $e->getAttribute('rel');
			$class =~ s/(^\s+|\s+$)//g;
			$class =~ s/\s+/ /g;
			my @class = split / /, $class;
			foreach my $c (@class)
				{ push @things, [('rel', $c)]; }

			$class = $e->getAttribute('rev');
			$class =~ s/(^\s+|\s+$)//g;
			$class =~ s/\s+/ /g;
			my @class = split / /, $class;
			foreach my $c (@class)
				{ push @things, [('rev', $c)]; }
		}

		foreach my $x (@things)
		{
			my ($attr, $c) = @$x;
			
			# rdf:type stuff
			if ($attr eq 'class' && $c =~ /^\-/)
			{
				my $rdftype = curie($this, substr($c,1), $e);
				
				if (($e->tagName eq 'a') && (length $rdftype > length $c))
				{
					my $triple = $this->graph('eRDF')->quick_rrr(
						$this->uri($e->getAttribute('href')),
						'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
						$rdftype);
					$this->graph->add_triple($triple);
				}
				elsif (length $rdftype > length $c)
				{
					my $triple = $this->graph('eRDF')->quick_rrr(
						$MySubject,
						'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
						$rdftype);
					$this->graph->add_triple($triple);
				}

				next;
			}
			
			# Only allow namespaced classes.
			my $nsrole = curie($this, $c, $e);
			next unless (length $nsrole > length $c);
			
			# Get value.
			my $valString = $e->getAttribute('title') 
				|| Swignition::GenericParser::Utils::STRINGIFY($e);
			my $valType;
			
			# Resource if it's an <img> element.
			if ($attr eq 'class' && lc($e->tagName) eq 'img')
			{
				$valString = $this->uri($e->getAttribute('src'));
				$valType   = 1;
			}
			elsif ($attr eq 'rel' && $e->tagName =~ /^(area|a|link)$/i)
			{
				$valString = $this->uri($e->getAttribute('href'));
				$valType   = 1;
			}
			elsif ($attr eq 'rev' && $e->tagName =~ /^(area|a|link)$/i)
			{
				my $triple = $this->graph('eRDF')->quick_rrr(
					$this->uri($e->getAttribute('href')),
					$nsrole,
					$ParentSubject);
				$this->graph->add_triple($triple);
				next;
			}
			elsif ($attr eq 'class' && $e->tagName =~ /^(area|a|link)$/i)
			{
				my $triple = $this->graph('eRDF')->quick_rrl(
					$this->uri($e->getAttribute('href')),
					$nsrole,
					Swignition::GenericParser::Utils::STRINGIFY($e));
				$this->graph->add_triple($triple);
				next;
			}
			
			# Resource if it has @id.
			if ($attr =~ /^(rel|rev)$/i && length $e->getAttribute('href'))
			{
				my $triple = $this->graph('eRDF')->quick_rrr(
					$ParentSubject,
					$nsrole,
					$this->uri($e->getAttribute('href')));
				$this->graph->add_triple($triple);
			}
			elsif (length $e->getAttribute('id'))
			{
				my $triple = $this->graph('eRDF')->quick_rrr(
					$ParentSubject,
					$nsrole,
					$MySubject);
				$this->graph->add_triple($triple);
			}
			else
			{
				my $triple = $valType ?
						$this->graph('eRDF')->quick_rrr(
							$ParentSubject,
							$nsrole,
							$valString) :
						$this->graph('eRDF')->quick_rrl(
							$ParentSubject,
							$nsrole,
							$valString) ;
				$this->graph->add_triple($triple);
			}

		}
	}
}


sub curie
{
	my $page  = shift;
	my $str   = shift;
	my $dom   = shift;
	my $xpath = $dom->getAttribute('_xpath') if ($dom);
	my $safe  = 0;
	
	# Cope with safe CURIEs.
	if ($str =~ /^\[(.*)\]$/)
	{
		$str  = $1;
		$safe = 1;
	}
	
	# If the string matches CURIE syntax, then resolve the CURIE.
	# This function allows a slightly looser CURIE syntax. Allows dots and dashes.
	if ($str =~ /^([a-z_][^\s\:\.\-]*)[\:\.\-](.*)$/i)
	{
		my $pfx = $1;
		my $sfx = $2;
		my $ns  = Swignition::Namespace::bestMatch($pfx, $xpath, @{$page->{Namespaces}});
		
		return $page->uri( $ns->{uri} . $sfx )
			if ($ns);
			
		return 'http://invalid.invalid/ns#'.$sfx
			if ($safe);
	}
	
	# If it wasn't a safe CURIE, then fall back to a URI.
	if (!$safe)
	{
		return $page->uri($str, {'require-absolute'=>1,'element'=>$dom});
	}
	
	return undef;
}


1;
